﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Dynamic;

namespace Visual_Studio_Test.DynamicObject
{
	public enum StringSearchOption
	{
		StartsWith,
		Contains,
		EndsWith
	}

	class ReadOnlyFile : System.Dynamic.DynamicObject
	{
		// Store the path to the file and the initial line count value.
		private string p_filePath;

		// Public constructor. Verify that file exists and store the path in 
		// the private variable.
		public ReadOnlyFile(string filePath)
		{
			if (!File.Exists(filePath))
			{
				throw new Exception("File path does not exist.");
			}

			p_filePath = filePath;
		}

		public List<string> GetPropertyValue(string propertyName,
									 StringSearchOption StringSearchOption = StringSearchOption.StartsWith,
									 bool trimSpaces = true)
		{
			StreamReader sr = null;
			List<string> results = new List<string>();
			string line = "";
			string testLine = "";

			try
			{
				sr = new StreamReader(p_filePath);

				while (!sr.EndOfStream)
				{
					line = sr.ReadLine();

					// Perform a case-insensitive search by using the specified search options.
					testLine = line.ToUpper();
					if (trimSpaces)		
						testLine = testLine.Trim(); 

					switch (StringSearchOption)
					{
						case StringSearchOption.StartsWith:
							if (testLine.StartsWith(propertyName.ToUpper())) 
							 results.Add(line); 
							break;
						case StringSearchOption.Contains:
							if (testLine.Contains(propertyName.ToUpper())) 
							 results.Add(line); 
							 break;
						case StringSearchOption.EndsWith:
							if (testLine.EndsWith(propertyName.ToUpper())) 
								results.Add(line); 
							break;
					}
				}
			}
			catch
			{
				// Trap any exception that occurs in reading the file and return null.
				results = null;
			}
			finally
			{
				if (sr != null) 
					sr.Close(); 
			}

			return results;
		}

		#region Override dynamic methods
		/// <summary>
		/// The TryGetMember method is called when a member of a dynamic class is requested and no arguments are specified
		/// </summary>
		/// <param name="binder" information about the referenced member </param>
		/// <param name="result">value of the member</param>
		/// <returns>Requested member exists?</returns>
		public override bool TryGetMember(GetMemberBinder binder,
										  out object result)
		{
			result = GetPropertyValue(binder.Name);
			return result == null ? false : true;
		}

		/// <summary>
		/// is called when a member of a dynamic class is requested with arguments
		/// </summary>
		/// <param name="binder"></param>
		/// <param name="args"></param>
		/// <param name="result"></param>
		/// <returns></returns>
		public override bool TryInvokeMember(InvokeMemberBinder binder,
											 object[] args,
											 out object result)
		{
			StringSearchOption StringSearchOption = StringSearchOption.StartsWith;
			bool trimSpaces = true;
			try
			{
				if (args.Length > 0) 
					StringSearchOption = (StringSearchOption)args[0]; 
			}
			catch
			{
				throw new ArgumentException("StringSearchOption argument must be a StringSearchOption enum value.");
			}

			try
			{
				if (args.Length > 1)  
					trimSpaces = (bool)args[1]; 
			}
			catch
			{
				throw new ArgumentException("trimSpaces argument must be a Boolean value.");
			}

			result = GetPropertyValue(binder.Name, StringSearchOption, trimSpaces);

			return result == null ? false : true;
		}


		#endregion


		#region ITesteable Members

		static public void Run()
		{
			dynamic rFile = new ReadOnlyFile(@"..\..\DynamicObject\TextFile1.txt");
			Console.WriteLine("-------Customers------------");
			Console.WriteLine("----------------------------");
			foreach (string line in rFile.Customer)
			{
				Console.WriteLine(line);
			}
			Console.WriteLine("----------------------------");
			Console.WriteLine("--------With web site-------");
			foreach (string line in rFile.http(StringSearchOption.Contains, true))
			{
				Console.WriteLine(line);
			}
		}

		#endregion
	}
}
